import { Vector3 } from "../../core/math/Vector3";
import { Vector2 } from "../../core/math/Vector2";
/**
 * @class
 * @memberof w.parser
 * @param {*} message 消息
 * @param {*} callback 处理完成的回调
 */
function createCylinder(message, callback) {
  let { radiusTop,
    radiusBottom,
    height,
    radialSegments,
    heightSegments,
    openEnded,
    thetaStart,
    thetaLength } = message;

  const scope = this;
  radialSegments = Math.floor( radialSegments );
  heightSegments = Math.floor( heightSegments );

  // buffers

  const indices = [];
  const vertices = [];
  const normals = [];
  const uvs = [];
  const groups = [];

  // helper variables
  let groupStart = 0;
  let index = 0;
  const indexArray = [];
  const halfHeight = height / 2;

  // generate geometry

  generateTorso();
  if ( openEnded === false ) {
    if ( radiusTop > 0 ) generateCap( true );
    if ( radiusBottom > 0 ) generateCap( false );
  }
  function generateTorso() {

    const vertex = new Vector3();
    const normal = new Vector3();

    const slope = ( radiusBottom - radiusTop ) / height;
    for (let y = 0; y <= heightSegments; y ++) {
      const indexRow = [];
      const v = y / heightSegments;
      const radius = v * (radiusBottom - radiusTop) + radiusTop;
      for (let x = 0; x <= radialSegments; x ++) {
        const u = x / radialSegments;
        const theta = u * thetaLength + thetaStart;
        const sinTheta = Math.sin( theta );
        const cosTheta = Math.cos( theta );
        // vertex
        vertex.x = radius * sinTheta;
        vertex.y = - v * height + halfHeight;
        vertex.z = radius * cosTheta;
        vertices.push( vertex.x, vertex.y, vertex.z );

        normal.set( cosTheta,sinTheta,slope).normalize();
        normals.push( normal.x, normal.y, normal.z );

        indexRow.push(index++);

      }
      indexArray.push(indexRow);

    }

    for (let x = 0; x < radialSegments; x ++) {
      for (let y = 0; y < heightSegments; y ++) {
        const a = indexArray[y][x];
        const b = indexArray[y + 1][x];
        const c = indexArray[y + 1][x + 1];
        const d = indexArray[y][x + 1];

        indices.push(a, b, d);
        indices.push(b, c, d);

      }

    }

  }

  function generateCap(top) {

    // save the index of the first center vertex
    const centerIndexStart = index;

    const uv = new Vector2();
    const vertex = new Vector3();

    let groupCount = 0;

    const radius = (top === true) ? radiusTop : radiusBottom;
    const sign = (top === true) ? 1 : - 1;

    for (let x = 1; x <= radialSegments; x ++) {
      // vertex
      vertices.push( 0, halfHeight * sign, 0 );
      // normal
      normals.push( 0, sign, 0 );
      // uv
      uvs.push( 0.5, 0.5 );
      // increase index
      index ++;
    }

    // save the index of the last center vertex
    const centerIndexEnd = index;

    // now we generate the surrounding vertices, normals and uvs

    for (let x = 0; x <= radialSegments; x ++) {

      const u = x / radialSegments;
      const theta = u * thetaLength + thetaStart;

      const cosTheta = Math.cos( theta );
      const sinTheta = Math.sin( theta );

      // vertex

      vertex.x = radius * sinTheta;
      vertex.y = halfHeight * sign;
      vertex.z = radius * cosTheta;
      vertices.push( vertex.x, vertex.y, vertex.z );

      // normal

      normals.push( 0, 0, sign );

      // uv

      uv.x = ( cosTheta * 0.5 ) + 0.5;
      uv.y = ( sinTheta * 0.5 * sign ) + 0.5;
      uvs.push( uv.x, uv.y );

      // increase index

      index ++;

    }

    // generate indices

    for ( let x = 0; x < radialSegments; x ++ ) {
      const c = centerIndexStart + x;
      const i = centerIndexEnd + x;
      if ( top === true ) {
        indices.push( i, i + 1, c );
      } else {
        indices.push( i + 1, i, c );
      }
      groupCount += 3;
    }
    // addGroup( groupStart, groupCount, top === true ? 1 : 2 );
    groupStart += groupCount;
  }

  function addGroup( start, count, materialIndex = 0 ) {
    groups.push( {
      start: start,
      count: count,
      materialIndex: materialIndex
    } );
  }
  callback({
    data: { indices: indices, position: vertices, normal: normals, texCood0: uvs },
    transferlist: []
  });
}

export { createCylinder }
